#!/usr/bin/env python
# -*- mode: python; coding: utf-8; -*-
##--------------------------------------------------------------------------##
##
## Copyright (C) 1998-2003 Markus Oberhumer <markus@oberhumer.com>
## Copyright (C) 2003 Mt. Hood Playing Card Co.
## Copyright (C) 2005-2010 Skomoroh <skomoroh@users.sourceforge.net>
## Copyright (C) 2010-2013 Jeremy Austin-Bardo <tjaustinbardo@gmail.com>
##
## This program is free software: you can redistribute it and/or modify
## it under the terms of the GNU General Public License as published by
## the Free Software Foundation, either version 3 of the License.
##
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
## GNU General Public License for more details.
##
## You should have received a copy of the GNU General Public License
## along with this program.  If not, see <http://www.gnu.org/licenses/>.
##
##--------------------------------------------------------------------------##
__docformat__ = 'restructuredtext en'
__all__ = []

from ... import formlib as layout
from ... import pilelib as stack
from ... import stackfill as fill
from ...gamelib import info as gi, game, state
from ...packlib import info as cs
from ...piles import hanafuda as hstack
from .. import picturegallery

GT, SL = gi.GT, gi.SL
Wrap = stack.StackWrapper


class TableauStack(hstack.Rank_RowStack):
    """
    Pile builds in rank by suit range for its id when base cards is 4th rank
    of same suit range.
    """
    _BOTTOM_IMAGE_ = 'suit'

    def cardsBuild(self, from_stack, cards):
        """
        cardsBuild(from_stack, cards) -> bool

        Check parent acccording to build capabilities. Check `TOPCARD` in suit
        range match its `id` / 8 and `BASECARD` is 4th rank. Base must match
        suit range

        :Parameters:
          from_stack : Stack
            sending pile
          cards : tuple
            cards from sending pile
        :returns: pile accepts ``cards``?
        """
        if not super(TableauStack, self).cardsBuild(from_stack, cards):
            return False
        suits = range(self.id / 8, (self.id / 8 + 4))
        if self.cards and (self.BASECARD['rank'] == cs.FOURTH
                           and self.TOPCARD['suit'] in suits):
            return super(TableauStack, self)._build_sequence(self.cards[-1:] +
                                                             cards)
        return cards[0]['suit'] in suits


class RowStack(stack.BasicRowStack):
    _BOTTOM_IMAGE_ = 'shade'

    def cardsBuild(self, from_stack, cards):
        """
        cardsBuild(from_stack, cards) -> bool

        Check parent acccording to build capabilities. Check pile empty or
        talon empty.

        :Parameters:
          from_stack : Stack
            sending pile
          cards : tuple
            cards from sending pile
        :returns: pile accepts ``cards``?
        """

        if not super(RowStack, self).cardsBuild(from_stack, cards):
            return False
        return not (self.cards or self.game.s['talon'].cards)


class FlowerArrangement(cs.Hanafuda_Deck, game.Game):
    """
    Arrange 2 deck on _tableau_.

    _layout_
      - row [24 over 3 rows, vert offset]
      - reserve [8 horz S row, vert offset]
      - talon [1 SE, no offset]

    :CVariables:
      _talon_ : pysollib.stack.Stack
        .. pysollib.stack.DealRowTalon (max_rounds=3)

        Deal 1 card per `s.rows` on click. No redeal.

      _tableau_ : pysollib.stack.Stack
        .. TableauStack (dir=-1, max_move=1, max_accept=1,
          max_cards=4, base_rank=FOURTH)

        Init 1 card. Piles build down in rank by same suit after base 4th
        rank of right suit. Base suit range: top row, Pine, Plum, Cherry, and
        Wisteria; center row, Iris, Peony, Bush Clover, and Eularia; and
        bottom row, Chrysanthemum, Maple, Willow, and Paulownia. Play top. Max
        4 card.

      _row_ : pysollib.stack.Stack
        .. RowStack (max_accept=1)

        Init 1 card. Build any after talon empty. Play top. Max 1 card.

      _hint_ : pysollib.hint.AbstractHint
        .. pysollib.games.picturegallery.Hint

    :todo: needs seperate layout
    """

    __info__ = dict(id=0x3061, name='Flower Arrangement',
                    category=cs.TYPE_HANAFUDA, game_type=GT.TWO_DECK, decks=2,
                    skill_level=SL.BALANCED, version='0.50fc')
    __author__ = 'Mt. Hood Playing Card'
    __version__ = 7.70

    _talon_ = stack.DealRowTalon
    _tableau_ = Wrap(TableauStack, dir=-1, max_move=1, max_accept=1,
                     max_cards=4, base_rank=cs.FOURTH)
    _row_ = Wrap(RowStack, max_accept=1)
    _hint_ = picturegallery.Hint

    def _create_game(self, playcards=10):
        l, s = layout.Layout(self), self.s
        self.table_size = (l.XM + 10 * l.XS + l.XM,
                            2 * l.YM + 3 * l._get_stack_height(4) +
                            l._get_stack_height(playcards))
        s['tableaux'] = []
        for x, y in l.col_block_iter(l.XM, l.YM, npiles=24, ncols=8,
                                     ycards=4):
            s['tableaux'].append(self._tableau_(x, y, game=self))
        y += l.YM
        for x in l.row_iter(l.XM, npiles=8):
            s['rows'].append(self._row_(x, y, game=self))
        x = l.XM + 8 * l.XS + l.XS / 2
        y = self.height - l.YS
        s['talon'] = self._talon_(x, y, self)
        l.set_ncards_text(s['talon'], 'se')
        self.sg['openstacks'] = s['tableaux'] + s['rows']
        self.sg['Talons'] = [s['talon']]
        self.sg['dropstacks'] = s['tableaux'] + s['rows']

    def _start(self):
        self.s['talon'].dealRow(rows=self.s['tableaux'], frames=0)
        self._play_sound('deal')
        self.s['talon'].dealRow()

    @property
    def is_complete(self):
        """
        Check `s.tableaux` has 4 cards each.
        """
        return (len(r.cards) == 4 for r in self.s['tableaux'])

    @state.move_state('fill')
    def _auto_fill(self, stack):
        """
        Fill empty `s.rows` with `s.talon` cards.
        """
        fill.fromTalon(self, stack, self.s['rows'])

    @property
    def _highlight_piles(self):
        """
        Get stacks to highlight for possible move.

        :return: empty.
        :rtype: tuple
        """
        return ()


PROVIDES = [FlowerArrangement]